

const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();

var path = require("path");
var fs = require("fs");

const { JSDOM } = require("jsdom");



const articleDirectoryPath = path.join(__dirname, "../../cyue-share-resource/article");
try {
	if (!fs.existsSync(articleDirectoryPath))
		fs.mkdirSync(articleDirectoryPath);
	else
	{
		if (fs.statSync(articleDirectoryPath).isFile())
		{
			fs.rmSync(articleDirectoryPath);
			fs.mkdirSync(articleDirectoryPath);
		}
	}
} catch(e) {
	console.error(e);
}

module.exports = {
    getArticleContentPath(publisherID, sortID, articleID)
    {
        return `${articleDirectoryPath}/${publisherID}/${sortID}/${articleID}.json`;
    },
    getArticleContentJSON(article)
    {
        try {
            let path = this.getArticleContentPath(article.publisher_id, article.sort_id, article.id);
            if (!fs.existsSync(path))
            {
                // 兼容旧文件
                path = `${articleDirectoryPath}/${article.publisher_id}/${article.sort_id}/${article.id}/${article.title}.json`;
            }
    
            const text = fs.readFileSync(
                    path,
                    "utf-8"
                );
            if (!text)
                return null;
            return JSON.parse(text);
        } catch (e) {
            // console.error(e);
            return null;
        }
    },


    /**
     * article content Element 转 数组
     * @param { Element } contentElement 
     * @returns 数组
     */
    articleContentElement2Array(contentElement)
    {
        const paragraphConvert2Array = function(paragraphElement)
        {
            const arr = [];
            const 遍历子元素 = function(element) {
                for (let index = 0; index < element.childNodes.length; index++) {
                    const node = element.childNodes[index];

                    // 同名元素
                    // <b><b>加粗</b></b>
                    if (node.nodeName === element.nodeName)
                    {
                        // 解开
                        遍历子元素(node);
                        continue;
                    }
                    // 有子元素
                    // <b><b>加粗</b></b>
                    // <b><i>加粗倾斜</i></b>
                    // <b><b>加粗</b><i>加粗倾斜</i></b>
                    try {
                        if (node.children.length && node.children.length > 0)
                        {
                            arr.push({
                                type:  node.nodeName.toLowerCase(),
                                value: paragraphConvert2Array(node)
                            });
                            continue;
                        }
                    } catch (e) {
                        console.error(e);
                    }
                    

                    // 普通文本节点
                    // <b>加粗</b>
                    if (node.nodeName === "#text" || node.nodeName === "DATE" || node.nodeName === "time")
                    {
                        arr.push({
                            type: node.nodeName.toLowerCase(),
                            value: node.textContent
                        });
                        continue;
                    }
                    // 普通情况
                    arr.push({
                        type: node.nodeName.toLowerCase(),
                        value: [
                            {
                                type: "#text",
                                value: node.textContent
                            }
                        ]
                    });
                }
            };
            遍历子元素(paragraphElement);
            return arr;
        };
    
        const blockquoteConvert2Array = function(blockquoteElement) {
            const arr = [];
            for (let i = 0; i < blockquoteElement.children.length; i++) {
                /** @type { Element } */
                const element = blockquoteElement.children[i];
                if (element.tagName === "P" || element.tagName === "PARAGRAPH")
                {
                    arr.push({
                        type: "paragraph",
                        value: paragraphConvert2Array(element)
                    });
                }
                else if (element.tagName === "FOOTER")
                {
                    arr.push({
                        type: "footer",
                        value: element.textContent
                    });
                }
            }
            return arr;
        };


        // 列表 转 []
        const listConvert2Array = function(listElement) {
            const arr = [];
            for (let index = 0; index < listElement.children.length; index++) {
                const element = listElement.children[index];
                if (element.tagName === "LIST-ITEM" || element.tagName === "ITEM")
                {
                    arr.push({
                        type: "li",
                        value: paragraphConvert2Array(element)
                    });
                    continue;
                }
                else if (element.tagName === "LIST-UNORDERED" || element.tagName === "UL")
                {
                    arr.push({
                        type: "ul",
                        value: listConvert2Array(element)
                    })
                }
                else if (element.tagName === "LIST-ORDERED" || element.tagName === "OL")
                {
                    arr.push({
                        type: "ol",
                        value: listConvert2Array(element)
                    })
                }
            }
            return arr;
        };
    
        const figureConvert2Array = function(figureElement) {
            const arr = [];
            for (let i = 0; i < figureElement.children.length; i++) {
                /** @type { Element } */
                const element = figureElement.children[i];
                if (element.tagName === "IMG" || element.tagName === "IMAGE")
                {
                    arr.push({
                        type: "img",
                        value: element.getAttribute("src"),
                        alt: element.getAttribute("alt")
                    });
                }
                else if (element.tagName === "FIGCAPTION")
                {
                    arr.push({
                        type: "figcaption",
                        value: element.textContent
                    });
                }
            }
            return arr;
        }
    
        const contentConvert2Array = function(contentElement) {
            const arr = [];
            for (let i = 0; i < contentElement.children.length; i++) {
                /** @type { Element } */
                const element = contentElement.children[i];
                
                
                if (element.tagName === "H2" || element.tagName === "SUBTITLE")
                {
                    arr.push({
                        type: "subtitle",
                        value: element.textContent
                    });
                }
                else if (element.tagName === "P" || element.tagName === "PARAGRAPH")
                {
                    arr.push({
                        type: "paragraph",
                        value: paragraphConvert2Array(element)
                    });
                }
                else if (element.tagName === "BLOCKQUOTE")
                {
                    arr.push({
                        type: "blockquote",
                        value: blockquoteConvert2Array(element)
                    });
                }
                else if (
                    element.tagName === "LIST-UNORDERED" ||
                    element.tagName === "UL"
                    )
                {
                    arr.push({
                        type: "ul",
                        value: listConvert2Array(element)
                    });
                }
                else if (
                    element.tagName === "LIST-ORDERED" ||
                    element.tagName === "OL"
                    )
                {
                    arr.push({
                        type: "ol",
                        value: listConvert2Array(element)
                    });
                }
                else if (element.tagName === "FIGURE")
                {
                    arr.push({
                        type: "figure",
                        value: figureConvert2Array(element)
                    });
                }
                else {
                    arr.push({
                        type: element.tagName.toLowerCase(),
                        value: element.textContent
                    });
                }
            }
    
            return arr;
        };
    1
        return contentConvert2Array(contentElement);
    },
    articleContentXML2Array(content)
    {
        const xmlDOM = new JSDOM(`<body>${content}</body>`);
        const contentElement = xmlDOM.window.document.querySelector("content") || xmlDOM.window.document.querySelector("main");
        // console.log(contentElement);
        return articleContentElement2Array(contentElement);
    },

    articleContentJSON2HTML(jsonArray)
    {
        if (!jsonArray)
            return null;

        const document = new JSDOM().window.document;
        const articleContentElement = document.createElement("div");

        for (let index = 0; index < jsonArray.length; index++) {
            const element = jsonArray[index];
    
            // 副标题
            if (element.type === "subtitle")
            {
                const h2 = document.createElement("h2");
                h2.className = "article-title-sub";
                h2.textContent = element.value;
                articleContentElement.appendChild(h2);
            }
            // 段落
            else if (element.type === "paragraph")
            {
                const p = document.createElement("p");
                const 遍历段落子节点 = function(node) {
                    if (typeof node.value === "string") {
                        node.value = node.value.replaceAll("<", "&lt;");
                    }
                    if (node.type === "text" || node.type === "#text")
                    {
                        p.innerHTML += node.value;
                        return;
                    }

                    // 老版本 和 date, time
                    if (!Array.isArray(node.value)) {
                        p.innerHTML += `<${node.type}>${node.value}</${node.type}>`
                    }
                    // 新版本
                    else {
                        p.innerHTML += `<${node.type}>`;
                        for (let index = 0; index < node.value.length; index++) {
                            const n = node.value[index];
                            遍历段落子节点(n);
                        }
                        p.innerHTML += `</${node.type}>`;
                    }
                };

                for (let j = 0; j < element.value.length; j++) {
                    const node = element.value[j];
                    遍历段落子节点(node);
                }
                articleContentElement.appendChild(p);
            }
            // 图片
            else if (element.type === "figure")
            {
                const figure = document.createElement("figure");
                figure.className = "article-figure";
                
                const [img, figcaption] = element.value;
                if (img)
                {
                    const imgElement = document.createElement("img");
                    imgElement.decoding = "async";
                    imgElement.loading = "lazy";
                    imgElement.src = img.value;
                    figure.appendChild(imgElement);
                }
                if (figcaption)
                {
                    const figcaptionElement = document.createElement("figcaption");
                    figcaptionElement.textContent = figcaption.value;
                    figure.appendChild(figcaptionElement);
                }
                articleContentElement.appendChild(figure);
            }
        }
    
        return articleContentElement.innerHTML;
    },
    
    
    async getSortIDByName(sortName)
    {
        const result = await prisma.article_sort.findUnique({
            select: {
                id: true
            },
            where:  {
                name: sortName
            }
        });
        // console.log(res);
        return result.id;
    },
    
    async searchSortIDByName(sortName)
    {
        const result = await prisma.article_sort.findMany({
            select: {
                id: true
            },
            where: {
                name: {
                    contains: sortName
                }
            }
        });
        const arr = new Array(result.length);
        for (let index = 0; index < result.length; index++) {
            const element = result[index];
            arr[index] = element.id;
        }
        return arr;
    },
    
    
    async getSortNameByID(sortID)
    {
        if (typeof sortID !== "number")
            sortID = parseInt(sortID);
        const result = await prisma.article_sort.findUnique({
            select: {
                name: true
            },
            where: {
                id: sortID
            }
        });
        // console.log(res);
        return result.name;
    },
    
    
    async getUserNicknameByID(uid)
    {
        if (typeof uid !== "number")
            uid = parseInt(uid);
        const result = await prisma.user.findUnique({
            select: {
                nickname: true
            },
            where: {
                id: uid
            }
        });
        // console.log(result);
        return result.nickname;
    },
    async getUserIDByNickname(nickname)
    {
        const result = await prisma.user.findUnique({
            select: {
                id: true
            },
            where: {
                nickname: nickname
            }
        });
        return result.id;
    },
    async getUserIDByUsername(username)
    {
        const result = await prisma.user.findUnique({
            select: {
                id: true
            },
            where: {
                username: username
            }
        });
        return result.id;
    },
    
    

    /**
     * 
     * @param { number } id 
     * @returns { Object | null }
     */
    async getArticleByID(id)
    {
        if (!id)
            return null;
        if (typeof id !== "number")
            id = parseInt(id);

        const article = await prisma.article.findUnique({
            include: {
                sort: true,
                user: {
                    select: {
                        nickname: true
                    }
                }
            },
            where: {
                id: id
            }
        });
        if (!article)
        {
            return null;
        }

        // 发布者，作者
        article.publisher = article.user.nickname;
        if (!article.author)
            article.author = article.user.nickname;

        article.sort_name = article.sort.name;
        article.date = `${article.date.getFullYear()}/${(article.date.getMonth() + 1)}/${article.date.getDate()}`;

        // 修改 content
        const contentJSON = this.getArticleContentJSON(article);
        if (contentJSON)
            article.content = contentJSON;

        return article;
    },

    async getArticleArrayByIDs(ids)
    {
        if (!ids || ids.length === 0)
            return null;

        const array = new Array(ids.length);
        for (let index = 0; index < ids.length; index++) {
            const id = ids[index];
            array[index] = await this.getArticleByID(id);
        }
        return array;
    }
};

